package zdream.pmfield.test.data.foe;

import org.junit.Before;
import org.junit.Test;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import zdream.pmfield.data.foe.FoeTemplate;
import zdream.pmfield.data.foe.Type;
import zdream.pmfield.storage.FoeTemplateStorage;
import zdream.pmfield.storage.FoesJsonLoader;
import zdream.pmfield.storage.JsonLoader;
import static zdream.pmfield.storage.FoeTemplateStorage.RES_PATH_FOES_JSON;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2023-11-16
 * @since 0.0.1
 */
public class FoeTemplateCase {
	FoeTemplateStorage storage;

	@Before
	public void before() {
		storage = new FoeTemplateStorage();
		storage.loadFoes();
	}

	@Test
	public void checkAllFoeTemplate() {
		ClassLoader loader = getClass().getClassLoader();
		InputStream inputStream = loader.getResourceAsStream(RES_PATH_FOES_JSON);
		final JsonElement element = JsonLoader.fromInputStream(inputStream);
		assertTrue(element.isJsonArray());

		JsonArray array = element.getAsJsonArray();
		Set<Pair> idSet = new HashSet<>();

		for (JsonElement jsonItem : array) {
			assertTrue(jsonItem.isJsonObject());

			JsonObject object = jsonItem.getAsJsonObject();
			assertTrue(object.has("id"));

			JsonElement idElement = object.get("id");
			assertTrue(idElement.isJsonPrimitive());
			JsonPrimitive idPrimitive = idElement.getAsJsonPrimitive();
			assertTrue(idPrimitive.isNumber());

			int id = idPrimitive.getAsInt();
			assertTrue(id > 0);
			System.out.println("现在正在检查 foes.json 中的元素: id=" + id);

			final FoeTemplate foe = FoesJsonLoader.loadOne(object);
			assertNotNull(foe);
			assertEquals(id, foe.id);

			Pair pair = new Pair(id, foe.subId);
			assertFalse(idSet.contains(pair));
			idSet.add(pair);

			assertNotNull(foe.name);
			assertTrue(foe.name.length() > 0);
			assertNotNull(foe.types);
			assertTrue(foe.types.length > 0);

			// 确保 type 没有相同的
			final Set<Type> typeSet = Arrays.stream(foe.types).collect(Collectors.toSet());
			assertEquals(typeSet.size(), foe.types.length);

			for (short bStat : foe.bStats) {
				assertTrue(bStat >= 1);
			}

			int sum = 0;
			for (short vStat : foe.vStats) {
				assertTrue(vStat >= 1);
				sum += vStat;
			}
			assertEquals(sum, foe.vStats.length * FoeTemplate.V_STAT_BASIC_VALUE);
		}
	}

	public static class Pair {
		public int id;
		public int subId;

		public Pair(int id, int subId) {
			this.id = id;
			this.subId = subId;
		}

		@Override
		public boolean equals(Object o) {
			if (this == o) return true;
			if (o == null || getClass() != o.getClass()) return false;
			Pair pair = (Pair) o;
			return id == pair.id && subId == pair.subId;
		}

		@Override
		public int hashCode() {
			return Objects.hash(id, subId);
		}
	}
}
